package org.dromara.business.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import org.dromara.business.domain.ContentCommentLikes;
import org.dromara.business.domain.UserLevel;
import org.dromara.business.domain.Video;
import org.dromara.business.domain.vo.UserInfoWebVo;
import org.dromara.business.mapper.*;
import org.dromara.business.sensitive.SensitiveWordFilter;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysUserVo;
import org.springframework.stereotype.Service;
import org.dromara.business.domain.bo.ContentCommentBo;
import org.dromara.business.domain.vo.ContentCommentVo;
import org.dromara.business.domain.ContentComment;
import org.dromara.business.service.IContentCommentService;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 统一内容评论Service业务层处理
 *
 * @author Hao Tong Xue
 * @date 2025-04-21
 */
@RequiredArgsConstructor
@Service
public class ContentCommentServiceImpl implements IContentCommentService {

    private final ContentCommentMapper baseMapper;
    private final SensitiveWordFilter sensitiveWordFilter;
    private final UserInfoMapper userInfoMapper;
    private final UserLevelMapper userLevelMapper;
    private final ContentCommentLikesMapper contentCommentLikesMapper;
    private final VideoMapper videoMapper;

    /**
     * 查询统一内容评论
     *
     * @param id 主键
     * @return 统一内容评论
     */
    @Override
    public ContentCommentVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询统一内容评论列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 统一内容评论分页列表
     */
    @Override
    public TableDataInfo<ContentCommentVo> queryPageList(ContentCommentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ContentComment> lqw = buildQueryWrapper(bo);
        Page<ContentCommentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        if (CollUtil.isNotEmpty(result.getRecords())) {

            List<UserInfoWebVo> userInfoWebVos = userInfoMapper.selectVoByIds(result.getRecords().stream().flatMap(a-> Stream.of(a.getCreateBy(), a.getReplyToUserId())).filter(Objects::nonNull).toList());
            List<UserLevel> userLevels = userLevelMapper.selectList();
            Map<Long, Integer> userLevelMap = userLevels.stream().collect(Collectors.toMap(UserLevel::getId, UserLevel::getUserLevel));
            Map<Long, UserInfoWebVo> userInfoWebVoMap = userInfoWebVos.stream().collect(Collectors.toMap(UserInfoWebVo::getId, s -> s));
            List<ContentCommentLikes> contentCommentLikesList = contentCommentLikesMapper.selectList(
                Wrappers.<ContentCommentLikes>lambdaQuery()
                    .in(ContentCommentLikes::getCommentId, result.getRecords().stream().map(ContentCommentVo::getId).toList())
                    .eq(BaseEntity::getCreateBy, LoginHelper.getUserId())
            );

            Map<Long, Integer> contentCommentLikesMap = new HashMap<>(contentCommentLikesList.size());
            if (CollUtil.isNotEmpty(contentCommentLikesList)) {
                contentCommentLikesMap = contentCommentLikesList.stream().collect(Collectors.toMap(ContentCommentLikes::getCommentId, ContentCommentLikes::getIsLiked));
            }
            for (ContentCommentVo record : result.getRecords()) {

                Map<String,Object> cacheUserInfo = RedisUtils.getCacheObject(GlobalConstants.USER_INFO_KEY + record.getCreateBy());
                if (cacheUserInfo != null) {
                    record.setCreateByName(cacheUserInfo.get("nickName") + "");
                    record.setCreateAvatar(cacheUserInfo.get("avatar") + "");
                }

                UserInfoWebVo userInfoWebVo = userInfoWebVoMap.get(record.getCreateBy());
                if (userInfoWebVo != null) {
                    record.setCreateFansNum(userInfoWebVo.getFansNum());
                    record.setCreateFollowNum(userInfoWebVo.getFollowNum());
                    record.setCreateUserLevel(userLevelMap.get(userInfoWebVo.getUserLevelId()));
                    record.setCreateUserSignature(userInfoWebVo.getSignature());
                }

                if (record.getReplyToUserId() != null) {
                    Map<String,Object> replyCacheUserInfo = RedisUtils.getCacheObject(GlobalConstants.USER_INFO_KEY + record.getReplyToUserId());
                    record.setReplyUserName(replyCacheUserInfo.get("nickName") + "");
                    record.setReplyUserAvatar(replyCacheUserInfo.get("avatar") + "");

                    UserInfoWebVo replyUserInfoWebVo = userInfoWebVoMap.get(record.getReplyToUserId());
                    if (userInfoWebVo != null) {
                        record.setReplyFansNum(replyUserInfoWebVo.getFansNum());
                        record.setReplyFollowNum(replyUserInfoWebVo.getFollowNum());
                        record.setReplyUserLevel(userLevelMap.get(replyUserInfoWebVo.getUserLevelId()));
                        record.setReplyUserSignature(replyUserInfoWebVo.getSignature());
                    }

                }

                Integer isLiked = contentCommentLikesMap.get(record.getId());
                record.setIsLiked(isLiked == null ? 2 : isLiked);
                record.setHasChildren(record.getReplyCount() > 0);

            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的统一内容评论列表
     *
     * @param bo 查询条件
     * @return 统一内容评论列表
     */
    @Override
    public List<ContentCommentVo> queryList(ContentCommentBo bo) {
        LambdaQueryWrapper<ContentComment> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ContentComment> buildQueryWrapper(ContentCommentBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ContentComment> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getContentType() != null, ContentComment::getContentType, bo.getContentType());
        lqw.like(StringUtils.isNotBlank(bo.getCommentText()), ContentComment::getCommentText, bo.getCommentText());
        lqw.eq(bo.getIsFeatured() != null, ContentComment::getIsFeatured, bo.getIsFeatured());
        lqw.eq(bo.getContentId() != null, ContentComment::getContentId, bo.getContentId());
        lqw.eq(bo.getParentId() != null, ContentComment::getParentId, bo.getParentId());
        lqw.eq(bo.getRootId() != null, ContentComment::getRootId, bo.getRootId());
//        lqw.orderByAsc(BaseEntity::getCreateTime);
        return lqw;
    }

    /**
     * 新增统一内容评论
     *
     * @param bo 统一内容评论
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(ContentCommentBo bo) {
        ContentComment add = MapstructUtils.convert(bo, ContentComment.class);
        validEntityBeforeSave(add);
        add.setCommentText(sensitiveWordFilter.filterContent(add.getCommentText()));

        if (bo.getRootId() != null && bo.getRootId() != 0) {

            ContentComment contentComment = baseMapper.selectById(bo.getRootId());
            contentComment.setReplyCount(contentComment.getReplyCount() + 1);
            baseMapper.updateById(contentComment);

        }

        if (bo.getContentType() == 1) {
            Video video = videoMapper.selectById(bo.getContentId());
            video.setCommentCount(video.getCommentCount() + 1);
            videoMapper.updateById(video);
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改统一内容评论
     *
     * @param bo 统一内容评论
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ContentCommentBo bo) {
        ContentComment update = MapstructUtils.convert(bo, ContentComment.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ContentComment entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除统一内容评论信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 点赞或取消
     * @param bo data 0 点赞 1 取消点赞
     */
    @Override
    public void likeCount(ContentCommentBo bo) {

        ContentComment contentComment = baseMapper.selectById(bo.getId());

        ContentCommentLikes contentCommentLikes = contentCommentLikesMapper.selectOne(
            Wrappers.<ContentCommentLikes>lambdaQuery()
                .eq(ContentCommentLikes::getCommentId, bo.getId())
                .eq(BaseEntity::getCreateBy, LoginHelper.getUserId())
        );

        if(bo.getType() == 0){

            if (contentCommentLikes == null) {
                contentCommentLikes = new ContentCommentLikes();
                contentCommentLikes.setCommentId(bo.getId());
                contentCommentLikes.setIsLiked(bo.getType());
                contentCommentLikesMapper.insert(contentCommentLikes);
                contentComment.setLikeCount(contentComment.getLikeCount() + 1);
            }else {

                if (contentCommentLikes.getIsLiked() == 1) {
                    contentComment.setLikeCount(contentComment.getLikeCount() + 1);
                    contentCommentLikes.setIsLiked(bo.getType());
                    contentCommentLikesMapper.updateById(contentCommentLikes);
                }else {
                    contentCommentLikesMapper.deleteById(contentCommentLikes.getId());
                    contentComment.setLikeCount(contentComment.getLikeCount() - 1);
                }

            }

        }else {

            if (contentCommentLikes == null) {
                contentCommentLikes = new ContentCommentLikes();
                contentCommentLikes.setCommentId(bo.getId());
                contentCommentLikes.setIsLiked(bo.getType());
                contentCommentLikesMapper.insert(contentCommentLikes);
            }else {
                if (contentCommentLikes.getIsLiked() == 0) {
                    contentComment.setLikeCount(contentComment.getLikeCount() - 1);
                    contentCommentLikes.setIsLiked(bo.getType());
                    contentCommentLikesMapper.updateById(contentCommentLikes);
                }else {
                    contentCommentLikesMapper.deleteById(contentCommentLikes.getId());
                }
            }

        }

        baseMapper.updateById(contentComment);

    }
}
